#define _GNU_SOURCE
#include "fastxml.h"

// 简化版本的安全XML解析器

// 内部函数声明
static xml_node_t* parse_element_safe(const char **xml, xml_node_t *parent, int depth);
static void skip_whitespace_safe(const char **xml);
static char* parse_tag_name_safe(const char **xml);

// 最大递归深度防止栈溢出
#define MAX_DEPTH 100

// 安全的解析XML字符串
xml_document_t* xml_parse_string_safe(const char *xml_string) {
    if (!xml_string) return NULL;
    
    xml_document_t *doc = malloc(sizeof(xml_document_t));
    if (!doc) return NULL;
    
    doc->root = NULL;
    doc->version = NULL;
    doc->encoding = NULL;
    
    const char *xml = xml_string;
    skip_whitespace_safe(&xml);
    
    // 跳过XML声明
    if (strncmp(xml, "<?xml", 5) == 0) {
        while (*xml && *xml != '>') xml++;
        if (*xml == '>') xml++;
        skip_whitespace_safe(&xml);
    }
    
    // 解析根元素
    if (*xml == '<' && *(xml + 1) != '/') {
        doc->root = parse_element_safe(&xml, NULL, 0);
    }
    
    return doc;
}

// 安全的解析元素
static xml_node_t* parse_element_safe(const char **xml, xml_node_t *parent, int depth) {
    if (!xml || !*xml || **xml != '<' || depth > MAX_DEPTH) {
        return NULL;
    }
    
    (*xml)++; // 跳过 '<'
    
    // 解析标签名
    char *tag_name = parse_tag_name_safe(xml);
    if (!tag_name) return NULL;
    
    printf("Debug: 解析元素 '%s', 深度 %d\n", tag_name, depth);
    
    xml_node_t *node = xml_create_node(XML_NODE_ELEMENT, tag_name, NULL);
    if (!node) {
        free(tag_name);
        return NULL;
    }
    
    node->parent = parent;
    
    // 跳过到 '>' 或 '/>'
    skip_whitespace_safe(xml);
    
    // 简单处理属性（暂时跳过）
    while (**xml && **xml != '>' && **xml != '/') {
        (*xml)++;
    }
    
    // 检查自闭合标签
    if (**xml == '/' && *(*xml + 1) == '>') {
        *xml += 2;
        free(tag_name);
        return node;
    }
    
    if (**xml == '>') {
        (*xml)++;
    } else {
        xml_free_node(node);
        free(tag_name);
        return NULL;
    }
    
    // 解析内容直到结束标签
    const char *content_start = *xml;
    int tag_name_len = strlen(tag_name);
    
    while (**xml) {
        if (**xml == '<' && *(*xml + 1) == '/') {
            // 检查是否是我们的结束标签
            if (strncmp(*xml + 2, tag_name, tag_name_len) == 0 &&
                *(*xml + 2 + tag_name_len) == '>') {
                
                // 提取文本内容
                if (*xml > content_start) {
                    int content_len = *xml - content_start;
                    char *content = malloc(content_len + 1);
                    if (content) {
                        strncpy(content, content_start, content_len);
                        content[content_len] = '\\0';
                        
                        // 简单去除前后空白
                        char *trimmed = content;
                        while (*trimmed && isspace(*trimmed)) trimmed++;
                        if (*trimmed) {
                            char *end = trimmed + strlen(trimmed) - 1;
                            while (end > trimmed && isspace(*end)) *end-- = '\\0';
                            if (*trimmed) {
                                node->content = strdup(trimmed);
                            }
                        }
                        free(content);
                    }
                }
                
                *xml += 3 + tag_name_len; // 跳过结束标签
                break;
            }
        }
        (*xml)++;
    }
    
    free(tag_name);
    return node;
}

// 安全的跳过空白
static void skip_whitespace_safe(const char **xml) {
    if (!xml || !*xml) return;
    while (**xml && isspace(**xml)) {
        (*xml)++;
    }
}

// 安全的解析标签名
static char* parse_tag_name_safe(const char **xml) {
    if (!xml || !*xml) return NULL;
    
    const char *start = *xml;
    
    while (**xml && **xml != '>' && **xml != '/' && !isspace(**xml)) {
        (*xml)++;
    }
    
    if (*xml == start) return NULL;
    
    int len = *xml - start;
    char *name = malloc(len + 1);
    if (name) {
        strncpy(name, start, len);
        name[len] = '\\0';
    }
    
    return name;
}